#!/usr/bin/env python3
"""
东方财富数据源实现
基于东方财富API的免费A股数据获取
"""

import pandas as pd
import requests
from datetime import datetime, timedelta
from typing import Dict, Any, Optional
import time
import json

from .base import BaseDataSource, DataSourceStatus
from ..utils.logger import get_logger

logger = get_logger("EastMoneySource")


class EastMoneySource(BaseDataSource):
    """东方财富数据源"""

    def __init__(self, config: Dict[str, Any] = None):
        super().__init__("eastmoney", config)
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Referer': 'http://quote.eastmoney.com/'
        })
        self._initialize_fetcher()

    def _initialize_fetcher(self):
        """初始化数据获取器"""
        try:
            self.update_status(DataSourceStatus.AVAILABLE)
            logger.info("东方财富数据源初始化成功")
        except Exception as e:
            self.update_status(DataSourceStatus.ERROR, str(e))
            logger.error(f"东方财富数据源初始化失败: {e}")

    def check_availability(self) -> bool:
        """检查数据源是否可用"""
        try:
            # 简单检查，不进行网络请求
            available = self.session is not None
            self.update_status(
                DataSourceStatus.AVAILABLE if available else DataSourceStatus.ERROR,
                None if available else "东方财富未可用"
            )
            return available
        except Exception as e:
            self.update_status(DataSourceStatus.ERROR, str(e))
            return False

    def get_stock_list(self) -> pd.DataFrame:
        """获取股票列表"""
        try:
            all_stocks = []
            page = 1
            page_size = 5000
            
            while True:
                url = "http://80.push2.eastmoney.com/api/qt/clist/get"
                params = {
                    'pn': str(page),
                    'pz': str(page_size),
                    'po': '1',
                    'np': '1',
                    'ut': 'bd1d9ddb04089700cf9c27f6f7426281',
                    'fltt': '2',
                    'invt': '2',
                    'fid': 'f3',
                    'fs': 'm:0 t:6,m:0 t:80,m:1 t:2,m:1 t:23',  # A股
                    'fields': 'f12,f14,f2,f3,f62,f184'
                }
                
                response = self.session.get(url, params=params, timeout=30)
                if response.status_code == 200:
                    data = response.json()
                    if data and 'data' in data and data['data'] and 'diff' in data['data']:
                        stocks = data['data']['diff']
                        if not stocks:
                            break
                            
                        for stock in stocks:
                            all_stocks.append({
                                'symbol': stock['f12'],
                                'name': stock['f14'],
                                'market': 'SH' if stock['f12'].startswith('6') else 'SZ'
                            })
                        
                        if len(stocks) < page_size:
                            break
                        page += 1
                    else:
                        break
                else:
                    break
                
                time.sleep(0.1)  # 避免请求过快
            
            if all_stocks:
                df = pd.DataFrame(all_stocks)
                df['data_source'] = 'eastmoney'
                return df
            
        except Exception as e:
            logger.error(f"东方财富获取股票列表失败: {e}")
            
        return pd.DataFrame()

    def fetch_history_data(self, symbol: str, interval: str,
                          start_date: str, end_date: str) -> pd.DataFrame:
        """获取历史数据"""
        try:
            # 构建股票代码
            market_code = '1' if symbol.startswith('6') else '0'
            stock_code = f"{market_code}.{symbol}"
            
            # 转换时间间隔
            klt = self._convert_interval(interval)
            
            url = "http://push2his.eastmoney.com/api/qt/stock/kline/get"
            params = {
                'secid': stock_code,
                'ut': 'fa5fd1943c7b386f172d6893dbfba10b',
                'fields1': 'f1,f2,f3,f4,f5,f6',
                'fields2': 'f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61',
                'klt': klt,
                'fqt': '1',
                'beg': start_date.replace('-', ''),
                'end': end_date.replace('-', ''),
                'lmt': '10000'
            }
            
            response = self.session.get(url, params=params, timeout=30)
            if response.status_code == 200:
                data = response.json()
                if data and 'data' in data and data['data'] and 'klines' in data['data']:
                    klines = data['data']['klines']
                    
                    if klines:
                        rows = []
                        for line in klines:
                            parts = line.split(',')
                            if len(parts) >= 6:
                                rows.append({
                                    'Date': pd.to_datetime(parts[0]),
                                    'Open': float(parts[1]),
                                    'Close': float(parts[2]),
                                    'High': float(parts[3]),
                                    'Low': float(parts[4]),
                                    'Volume': float(parts[5])
                                })
                        
                        if rows:
                            df = pd.DataFrame(rows)
                            df = df[['Date', 'Open', 'High', 'Low', 'Close', 'Volume']].sort_values('Date')
                            
                            # 添加延迟避免频率限制
                            time.sleep(0.1)
                            
                            return df
            
            return pd.DataFrame()

        except Exception as e:
            logger.error(f"东方财富获取历史数据失败 {symbol}: {e}")
            return pd.DataFrame()

    def _convert_interval(self, interval: str) -> str:
        """转换时间间隔格式"""
        interval_map = {
            '1m': '1',
            '5m': '5',
            '15m': '15',
            '30m': '30',
            '1h': '60',
            '1d': '101',
            '1w': '102',
            '1M': '103'
        }
        return interval_map.get(interval, '101')

    def get_stock_info(self, symbol: str) -> Dict[str, Any]:
        """获取股票信息"""
        try:
            market_code = '1' if symbol.startswith('6') else '0'
            stock_code = f"{market_code}.{symbol}"
            
            url = "http://push2.eastmoney.com/api/qt/stock/get"
            params = {
                'ut': 'fa5fd1943c7b386f172d6893dbfba10b',
                'invt': '2',
                'fltt': '2',
                'fields': 'f57,f58,f162,f163,f164,f165',
                'secid': stock_code
            }
            
            response = self.session.get(url, params=params, timeout=10)
            if response.status_code == 200:
                data = response.json()
                if data and 'data' in data and data['data']:
                    stock_data = data['data']
                    return {
                        'symbol': symbol,
                        'name': stock_data.get('f58', 'Unknown'),
                        'market': 'SH' if symbol.startswith('6') else 'SZ'
                    }
            
            return {}
        except Exception as e:
            logger.error(f"东方财富获取股票信息失败 {symbol}: {e}")
            return {}
